1 /*******************************************************************************
2 * Copyright (c) 2012-2014 University of Stuttgart.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * and the Apache License 2.0 which both accompany this distribution,
6 * and are available at http://www.eclipse.org/legal/epl-v10.html
7 * and http://www.apache.org/licenses/LICENSE-2.0
10 * Oliver Kopp - initial API and implementation
11 * C. Timurhan Sungur - jClouds preferences
12 *******************************************************************************/
13 package org.eclipse.winery.repository;
16 import java.io.FileInputStream;
17 import java.io.FileNotFoundException;
18 import java.io.IOException;
19 import java.io.InputStream;
20 import java.security.AccessControlException;
21 import java.util.Locale;
22 import java.util.Properties;
24 import javax.servlet.ServletContext;
25 import javax.servlet.ServletContextEvent;
26 import javax.servlet.ServletContextListener;
28 import org.eclipse.winery.common.TOSCADocumentBuilderFactory;
29 import org.eclipse.winery.repository.backend.IRepository;
30 import org.eclipse.winery.repository.backend.filebased.FilebasedRepository;
31 import org.eclipse.winery.repository.backend.filebased.GitBasedRepository;
32 import org.eclipse.winery.repository.runtimeintegration.OpenTOSCAContainerConnection;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
36 public class Prefs implements ServletContextListener {
38 // set by the constructors
39 // We have to do this hack as the servlet container initializes this class
40 // on its own and we want to have a *single* instance of this class.
41 public static Prefs INSTANCE;
43 private static final Logger logger = LoggerFactory.getLogger(Prefs.class);
45 protected IRepository repository = null;
47 private ServletContext context;
49 private Boolean isContainerLocallyAvailable = null;
51 private Boolean isRestDocDocumentationAvailable = null;
53 private Boolean isPlanBuilderAvailable = null;
55 // location of the winery topology modeler
56 private String wineryTopologyModelerPath = null;
58 // the properties from winery.properties
59 protected Properties properties = null;
61 // package visibility to ease testing
62 static final String PROP_JCLOUDS_CONTEXT_PROVIDER = "jclouds.context.provider";
63 static final String PROP_JCLOUDS_CONTEXT_IDENTITY = "jclouds.context.identity";
64 static final String PROP_JCLOUDS_CONTEXT_CREDENTIAL = "jclouds.context.credential";
65 static final String PROP_JCLOUDS_BLOBSTORE_LOCATION = "jclouds.blobstore.location";
66 static final String PROP_JCLOUDS_CONTAINERNAME = "jclouds.blobstore.container";
67 static final String PROP_JCLOUDS_END_POINT = "jclouds.blobstore.endpoint";
69 static final String PROP_BPMN4TOSCA_MODELER_URI = "bpmn4toscamodelerBaseURI";
73 * This constructor is called at handling at servlets, too. Therefore, we
74 * make it private. If testing is needed, an additional paramater has to be
78 Prefs.INSTANCE = this;
82 * Constructor for Unit testing ONLY!
84 * @param initializeRepository true if the repository should be initialized
85 * as provided in winery.properties
87 * @warning Do not call! (except from Unit testing code)
89 protected Prefs(boolean initializeRepository) throws IOException {
92 // emulate behavior of doInitialization(Context)
93 Properties p = new Properties();
94 InputStream is = this.getClass().getClassLoader().getResourceAsStream("winery.properties");
100 if (initializeRepository) {
101 this.doRepositoryInitialization();
106 * Initialization code for the repository. Should go into separate class,
107 * but being here should be OK for a prototype
109 * Called from both the constructor for JUnit and the servlet-based
112 * Pre-Condition: this.properties is set.
114 private void doRepositoryInitialization() {
115 assert (this.properties != null);
117 String provider = this.properties.getProperty(Prefs.PROP_JCLOUDS_CONTEXT_PROVIDER);
118 if (provider != null) {
119 // repository runs via jclouds
120 // String identity = this.properties.getProperty(Prefs.PROP_JCLOUDS_CONTEXT_IDENTITY);
121 // String credential = this.properties.getProperty(Prefs.PROP_JCLOUDS_CONTEXT_CREDENTIAL);
122 // String location = this.properties.getProperty(Prefs.PROP_JCLOUDS_BLOBSTORE_LOCATION);
123 // String containerName = this.properties.getProperty(Prefs.PROP_JCLOUDS_CONTAINERNAME);
124 // String endPoint = this.properties.getProperty(Prefs.PROP_JCLOUDS_END_POINT);
125 Prefs.logger.error("jClouds is currently not supported due to jClouds not yet approved by Eclipse. Falling back to local storages");
127 // Prefs.logger.info("Using jclouds as interface to the repository");
128 // this.repository = new JCloudsBasedRepository(provider, identity, credential, location, containerName, endPoint);
130 if (provider == null) {
131 String repositoryLocation = this.properties.getProperty("repositoryPath");
132 Prefs.logger.debug("Repository location: {}", repositoryLocation);
133 Prefs.logger.debug("Trying git-based backend");
135 this.repository = new GitBasedRepository(repositoryLocation);
136 Prefs.logger.debug("git-based backend is used");
137 } catch (Throwable e) {
138 Prefs.logger.trace(e.getMessage());
139 Prefs.logger.debug("There seems to be no git repository at the specified location. We fall back to the file-based repository");
140 this.repository = new FilebasedRepository(repositoryLocation);
145 private void doInitialization(ServletContext ctx) {
146 if (Locale.getDefault() != Locale.ENGLISH) {
149 // org.eclipse.winery.repository.filesystem.Utils.returnFile(File,
151 Locale.setDefault(Locale.ENGLISH);
152 } catch (AccessControlException e) {
153 // Happens at Google App Engine
154 Prefs.logger.error("Could not switch locale to English", e);
161 final String fn = "/WEB-INF/classes/winery.properties";
162 Prefs.logger.debug("Trying to read ".concat(ctx.getRealPath(fn)));
163 InputStream inStream = ctx.getResourceAsStream(fn);
164 // alternative: InputStream inStream = this.getClass().getClassLoader().getResourceAsStream("winery.properties");
165 Properties p = new Properties();
166 if (inStream == null) {
167 Prefs.logger.info(fn + " does not exist.");
169 // We search for winery.properties on the filesystem in the repository
171 File propFile = new File(FilebasedRepository.getDefaultRepositoryFilePath(), "winery.properties");
172 Prefs.logger.info("Trying " + propFile.getAbsolutePath());
173 if (propFile.exists()) {
174 Prefs.logger.info("Found");
175 // if winery.property exists in the root of the default repository path (~/winery-repository), load it
176 try (InputStream is2 = new FileInputStream(propFile)) {
178 } catch (IOException e) {
179 Prefs.logger.error("Could not load winery.properties", e);
182 Prefs.logger.info("Not found");
189 } catch (IOException e) {
190 Prefs.logger.error("Could not close stream of winery.properties", e);
192 } catch (FileNotFoundException e) {
193 // OK if file does not exist
194 } catch (IOException e) {
195 Prefs.logger.error("Could not load winery.properties", e);
199 this.wineryTopologyModelerPath = p.getProperty("topologymodeler");
201 // make the properties known in the class
204 this.doRepositoryInitialization();
206 // Initialize XSD validation in the background. Takes up a few seconds.
207 // If we do not do it here, the first save by a user takes a few seconds, which is inconvenient
212 Prefs.logger.debug("Initializing XML validation");
213 @SuppressWarnings("unused")
214 TOSCADocumentBuilderFactory tdbf = TOSCADocumentBuilderFactory.INSTANCE;
215 Prefs.logger.debug("Initialized XML validation");
220 public IRepository getRepository() {
221 return this.repository;
225 public void contextInitialized(ServletContextEvent arg0) {
226 Prefs.INSTANCE.doInitialization(arg0.getServletContext());
230 public void contextDestroyed(ServletContextEvent arg0) {
231 // nothing to do at tear down
235 * @return the path of the root resource
237 public String getResourcePath() {
238 return this.context.getContextPath();
242 * @return the path to the winery topology modeler. Without trailing slash
244 public String getWineryTopologyModelerPath() {
245 if (this.wineryTopologyModelerPath == null) {
246 // derive the path from the current path
247 String res = this.getResourcePath();
248 if (res.endsWith("/")) {
249 res = res.substring(0, res.length() - 1);
251 int pos = res.lastIndexOf("/");
253 res = "/winery-topologymodeler";
255 res = res.substring(0, pos);
256 res = res + "winery-topologymodeler";
260 assert (this.wineryTopologyModelerPath != null);
261 return this.wineryTopologyModelerPath;
266 * Returns the read content from winery.properties.
268 * @return the internal object held by this class. Manipulations on this
269 * object may cause trouble.
271 public Properties getProperties() {
272 return this.properties;
276 * @return the version of winery
278 public String getVersion() {
279 return Version.VERSION;
283 * @return true if the OpenTOSCA container is locally available
285 public boolean isContainerLocallyAvailable() {
286 if (this.isContainerLocallyAvailable == null) {
287 // we initialize the variable at the first read
288 // The container and Winery are started simultaneously
289 // Therefore, the container might not be available if Winery is starting
290 // When checking at the first read, chances are high that the container started
291 this.isContainerLocallyAvailable = OpenTOSCAContainerConnection.isContainerLocallyAvailable();
293 return this.isContainerLocallyAvailable;
297 * @return true if the plan generator is available
299 public boolean isPlanBuilderAvailable() {
300 // similar implementation as isContainerLocallyAvailable()
301 if (this.isPlanBuilderAvailable == null) {
302 String planBuilderURI = "http://localhost:1339/planbuilder";
303 this.isPlanBuilderAvailable = Utils.isResourceAvailable(planBuilderURI);
305 return this.isPlanBuilderAvailable;
309 * Quick hack to check whether a RestDoc documentation is available at
310 * /restdoc.html. We do not deliver
312 public boolean isRestDocDocumentationAvailable() {
313 String path = "http://localhost:8080/restdoc.html";
314 if (this.isRestDocDocumentationAvailable == null) {
315 // we initialize the variable at the first read
316 // The container and Winery are started simultaneously
317 // Therefore, the container might not be available if Winery is starting
318 // When checking at the first read, chances are high that the container started
319 this.isRestDocDocumentationAvailable = Utils.isResourceAvailable(path);
321 return this.isRestDocDocumentationAvailable;
325 * @return the base URL of the BPMN4TOSCA plan modeler. NULL if not
326 * configured. May also be empty.
328 public String getBPMN4TOSCABaseURL() {
329 return this.properties.getProperty(Prefs.PROP_BPMN4TOSCA_MODELER_URI);