001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.servicemix.jbi.container;
018    
019    import java.io.File;
020    import java.io.IOException;
021    import java.util.Map;
022    import java.util.concurrent.ConcurrentHashMap;
023    import java.util.concurrent.atomic.AtomicBoolean;
024    
025    import javax.jbi.JBIException;
026    
027    import org.apache.commons.logging.Log;
028    import org.apache.commons.logging.LogFactory;
029    import org.apache.servicemix.jbi.framework.ComponentMBeanImpl;
030    import org.apache.servicemix.jbi.management.BaseSystemService;
031    import org.apache.servicemix.jbi.util.FileUtil;
032    import org.apache.servicemix.jbi.util.FileVersionUtil;
033    
034    /**
035     * Holder for environment information
036     * 
037     * <component-name> (component root dir)
038     *   |-> version_X (versionned dir)
039     *   \-> workspace (workspace dir)
040     *   
041     * ServiceAssembly root
042     *   \-> version_X (versionned dir)
043     *     |-> install (unzip dir)
044     *     \-> sus (service units dir)
045     *       |-> <component-name>
046     *         |-> <service-unit-name>
047     * 
048     * @version $Revision: 564900 $
049     */
050    public class EnvironmentContext extends BaseSystemService implements EnvironmentContextMBean {
051        
052        private static final Log LOG = LogFactory.getLog(EnvironmentContext.class);
053    
054        private File jbiRootDir;
055        private File componentsDir;
056        private File installationDir;
057        private File deploymentDir;
058        private File sharedLibDir;
059        private File serviceAssembliesDir;
060        private File tmpDir;
061        private Map envMap = new ConcurrentHashMap();
062        private AtomicBoolean started = new AtomicBoolean(false);
063    
064        /**
065         * @return the current version of servicemix
066         */
067        public static String getVersion() {
068            String answer = null;
069            Package p = Package.getPackage("org.apache.servicemix");
070            if (p != null) {
071                answer = p.getImplementationVersion();
072            }
073            return answer;
074        }
075    
076        /**
077         * Get Description
078         * @return description
079         */
080        public String getDescription() {
081            return "Manages Environment for the Container";
082        }
083    
084        /**
085         * @return Returns the componentsDir.
086         */
087        public File getComponentsDir() {
088            return componentsDir;
089        }
090    
091        /**
092         * @return Returns the installationDir.
093         */
094        public File getInstallationDir() {
095            return installationDir;
096        }
097    
098        /**
099         * Set the installationDir - rge default location
100         * is root/<container name>/installation
101         * @param installationDir
102         */
103        public void setInstallationDir(File installationDir) {
104            this.installationDir = installationDir;
105        }
106    
107        /**
108         * @return Returns the deploymentDir.
109         */
110        public File getDeploymentDir() {
111            return deploymentDir;
112        }
113    
114        /**
115         * @param deploymentDir The deploymentDir to set.
116         */
117        public void setDeploymentDir(File deploymentDir) {
118            this.deploymentDir = deploymentDir;
119        }
120    
121        /**
122         * 
123         * @return Returns the shared library directory
124         */
125        public File getSharedLibDir() {
126            return sharedLibDir;
127        }
128    
129        /**
130         * @return Returns the tmpDir
131         */
132        public File getTmpDir() {
133            if (tmpDir != null) {
134                FileUtil.buildDirectory(tmpDir);
135            }
136            return tmpDir;
137        }
138    
139        /**
140         * @return Returns service asseblies directory
141         */
142        public File getServiceAssembliesDir() {
143            return serviceAssembliesDir;
144        }
145    
146        /**
147         * Initialize the Environment
148         * 
149         * @param container
150         * @param rootDirPath
151         * @exception javax.jbi.JBIException if the root directory informed could not be created or it is not a directory
152         */
153        public void init(JBIContainer container, String rootDirPath) throws JBIException {
154            super.init(container);
155            jbiRootDir = new File(rootDirPath);
156            buildDirectoryStructure();
157        }
158    
159        protected Class getServiceMBean() {
160            return EnvironmentContextMBean.class;
161        }
162    
163        /**
164         * Start the item.
165         * 
166         * @exception javax.jbi.JBIException if the item fails to start.
167         */
168        public void start() throws javax.jbi.JBIException {
169            if (started.compareAndSet(false, true)) {
170                super.start();
171            }
172        }
173    
174        /**
175         * Stop the item. This suspends current messaging activities.
176         * 
177         * @exception javax.jbi.JBIException if the item fails to stop.
178         */
179        public void stop() throws javax.jbi.JBIException {
180            if (started.compareAndSet(true, false)) {
181                super.stop();
182            }
183        }
184    
185        /**
186         * Shut down the item. The releases resources, preparatory to uninstallation.
187         * 
188         * @exception javax.jbi.JBIException if the item fails to shut down.
189         */
190        public void shutDown() throws javax.jbi.JBIException {
191            super.shutDown();
192            envMap.clear();
193            container.getManagementContext().unregisterMBean(this);
194        }
195    
196        /**
197         * register the ComponentConnector
198         * 
199         * @param connector
200         * @return the CompponentEnvironment
201         * @throws JBIException
202         */
203        public ComponentEnvironment registerComponent(ComponentMBeanImpl connector) throws JBIException {
204            return registerComponent(null, connector);
205        }
206    
207        /**
208         * register the ComponentConnector
209         * 
210         * @param connector
211         * @return the CompponentEnvironment
212         * @throws JBIException
213         */
214        public ComponentEnvironment registerComponent(ComponentEnvironment result, ComponentMBeanImpl connector) throws JBIException {
215            if (result == null) {
216                result = new ComponentEnvironment();
217            }
218            if (!connector.isPojo()) {
219                if (container.isEmbedded()) {
220                    throw new JBIException("JBI component can not be installed in embedded mode");
221                }
222                // add workspace root and stats root ..
223                try {
224                    String name = connector.getComponentNameSpace().getName();
225                    if (result.getComponentRoot() == null) {
226                        File componentRoot = getComponentRootDir(name);
227                        FileUtil.buildDirectory(componentRoot);
228                        result.setComponentRoot(componentRoot);
229                    }
230                    if (result.getWorkspaceRoot() == null) {
231                        File privateWorkspace = createWorkspaceDirectory(name);
232                        result.setWorkspaceRoot(privateWorkspace);
233                    }
234                    if (result.getStateFile() == null) {
235                        File stateFile = FileUtil.getDirectoryPath(result.getComponentRoot(), "state.xml");
236                        result.setStateFile(stateFile);
237                    }
238                } catch (IOException e) {
239                    throw new JBIException(e);
240                }
241            }
242            result.setLocalConnector(connector);
243            envMap.put(connector, result);
244            return result;
245        }
246    
247        /**
248         * Get root directory for a Component
249         * 
250         * @param componentName
251         * @return directory for deployment/workspace etc
252         * @throws IOException
253         */
254        public File getComponentRootDir(String componentName) {
255            if (getComponentsDir() == null) {
256                return null;
257            }
258            return FileUtil.getDirectoryPath(getComponentsDir(), componentName);
259        }
260    
261        /**
262         * Create root directory for a Component
263         * 
264         * @param componentName
265         * @return directory for deployment/workspace etc
266         * @throws IOException
267         */
268        public File createComponentRootDir(String componentName) throws IOException {
269            if (getComponentsDir() == null) {
270                return null;
271            }
272            return FileUtil.getDirectoryPath(getComponentsDir(), componentName);
273        }
274    
275        /**
276         * Get a new versionned directory for installation
277         * 
278         * @param componentName
279         * @return
280         * @throws IOException
281         */
282        public File getNewComponentInstallationDir(String componentName) throws IOException {
283            File result = getComponentRootDir(componentName);
284            // get new version dir
285            return FileVersionUtil.getNewVersionDirectory(result);
286        }
287    
288        /**
289         * Create installation directory for a Component
290         * 
291         * @param componentName
292         * @return directory to deploy in
293         * @throws IOException
294         */
295        public File getComponentInstallationDir(String componentName) throws IOException {
296            File result = getComponentRootDir(componentName);
297            // get the version directory
298            return FileVersionUtil.getLatestVersionDirectory(result);
299        }
300    
301        public ComponentEnvironment getNewComponentEnvironment(String compName) throws IOException {
302            File rootDir = FileUtil.getDirectoryPath(getComponentsDir(), compName);
303            File instDir = FileVersionUtil.getNewVersionDirectory(rootDir);
304            File workDir = FileUtil.getDirectoryPath(rootDir, "workspace");
305            File stateFile = FileUtil.getDirectoryPath(rootDir, "state.xml");
306            ComponentEnvironment env = new ComponentEnvironment();
307            env.setComponentRoot(rootDir);
308            env.setInstallRoot(instDir);
309            env.setWorkspaceRoot(workDir);
310            env.setStateFile(stateFile);
311            return env;
312        }
313    
314        public ComponentEnvironment getComponentEnvironment(String compName) throws IOException {
315            File rootDir = FileUtil.getDirectoryPath(getComponentsDir(), compName);
316            File instDir = FileVersionUtil.getLatestVersionDirectory(rootDir);
317            File workDir = FileUtil.getDirectoryPath(rootDir, "workspace");
318            File stateFile = FileUtil.getDirectoryPath(rootDir, "state.xml");
319            ComponentEnvironment env = new ComponentEnvironment();
320            env.setComponentRoot(rootDir);
321            env.setInstallRoot(instDir);
322            env.setWorkspaceRoot(workDir);
323            env.setStateFile(stateFile);
324            return env;
325        }
326    
327        public ServiceAssemblyEnvironment getNewServiceAssemblyEnvironment(String saName) throws IOException {
328            File rootDir = FileUtil.getDirectoryPath(getServiceAssembliesDir(), saName);
329            File versDir = FileVersionUtil.getNewVersionDirectory(rootDir);
330            File instDir = FileUtil.getDirectoryPath(versDir, "install");
331            File susDir = FileUtil.getDirectoryPath(versDir, "sus");
332            File stateFile = FileUtil.getDirectoryPath(rootDir, "state.xml");
333            ServiceAssemblyEnvironment env = new ServiceAssemblyEnvironment();
334            env.setRootDir(rootDir);
335            env.setInstallDir(instDir);
336            env.setSusDir(susDir);
337            env.setStateFile(stateFile);
338            return env;
339        }
340    
341        public ServiceAssemblyEnvironment getServiceAssemblyEnvironment(String saName) {
342            File rootDir = FileUtil.getDirectoryPath(getServiceAssembliesDir(), saName);
343            File versDir = FileVersionUtil.getLatestVersionDirectory(rootDir);
344            File instDir = FileUtil.getDirectoryPath(versDir, "install");
345            File susDir = FileUtil.getDirectoryPath(versDir, "sus");
346            File stateFile = FileUtil.getDirectoryPath(rootDir, "state.xml");
347            ServiceAssemblyEnvironment env = new ServiceAssemblyEnvironment();
348            env.setRootDir(rootDir);
349            env.setInstallDir(instDir);
350            env.setSusDir(susDir);
351            env.setStateFile(stateFile);
352            return env;
353        }
354    
355        /**
356         * Create workspace directory for a Component
357         * 
358         * @param componentName
359         * @return directory workspace
360         * @throws IOException
361         */
362        public File createWorkspaceDirectory(String componentName) throws IOException {
363            File result = FileUtil.getDirectoryPath(getComponentsDir(), componentName);
364            result = FileUtil.getDirectoryPath(result, "workspace");
365            FileUtil.buildDirectory(result);
366            return result;
367        }
368    
369        /**
370         * deregister the ComponentConnector
371         * 
372         * @param connector
373         * @param doDelete true if component is to be deleted
374         */
375        public void unreregister(ComponentMBeanImpl connector) {
376            this.envMap.remove(connector);
377        }
378    
379        /**
380         * Remove the Component root directory from the local file system
381         * 
382         * @param componentName
383         */
384        public void removeComponentRootDirectory(String componentName) {
385            File file = getComponentRootDir(componentName);
386            if (file != null) {
387                if (!FileUtil.deleteFile(file)) {
388                    LOG.warn("Failed to remove directory structure for component [version]: " + componentName + " [" + file.getName() + ']');
389                } else {
390                    LOG.info("Removed directory structure for component [version]: " + componentName + " [" + file.getName() + ']');
391                }
392            }
393        }
394    
395        /**
396         * create a shared library directory
397         * 
398         * @param name
399         * @return directory
400         * @throws IOException
401         */
402        public File createSharedLibraryDirectory(String name) {
403            File result = FileUtil.getDirectoryPath(getSharedLibDir(), name);
404            FileUtil.buildDirectory(result);
405            return result;
406        }
407    
408        /**
409         * remove shared library directory
410         * @param name
411         * @throws IOException
412         */
413        public void removeSharedLibraryDirectory(String name) {
414            File result = FileUtil.getDirectoryPath(getSharedLibDir(), name);
415            FileUtil.deleteFile(result);
416        }
417    
418        private void buildDirectoryStructure() throws JBIException {
419            // We want ServiceMix to be able to run embedded
420            // so do not create the directory structure if the root does not exist
421            if (container.isEmbedded()) {
422                return;
423            }
424            try {
425                jbiRootDir = jbiRootDir.getCanonicalFile();
426                if (!jbiRootDir.exists()) {
427                    if (!jbiRootDir.mkdirs()) {
428                        throw new JBIException("Directory could not be created: " + jbiRootDir.getCanonicalFile());
429                    }
430                } else if (!jbiRootDir.isDirectory()) {
431                    throw new JBIException("Not a directory: " + jbiRootDir.getCanonicalFile());
432                }
433                if (installationDir == null) {
434                    installationDir = FileUtil.getDirectoryPath(jbiRootDir, "install");
435                }
436                installationDir = installationDir.getCanonicalFile();
437                if (deploymentDir == null) {
438                    deploymentDir = FileUtil.getDirectoryPath(jbiRootDir, "deploy");
439                }
440                deploymentDir = deploymentDir.getCanonicalFile();
441                componentsDir = FileUtil.getDirectoryPath(jbiRootDir, "components").getCanonicalFile();
442                tmpDir = FileUtil.getDirectoryPath(jbiRootDir, "tmp").getCanonicalFile();
443                sharedLibDir = FileUtil.getDirectoryPath(jbiRootDir, "sharedlibs").getCanonicalFile();
444                serviceAssembliesDir = FileUtil.getDirectoryPath(jbiRootDir, "service-assemblies").getCanonicalFile();
445                //actually create the sub directories
446                FileUtil.buildDirectory(installationDir);
447                FileUtil.buildDirectory(deploymentDir);
448                FileUtil.buildDirectory(componentsDir);
449                FileUtil.buildDirectory(tmpDir);
450                FileUtil.buildDirectory(sharedLibDir);
451                FileUtil.buildDirectory(serviceAssembliesDir);
452            } catch (IOException e) {
453                throw new JBIException(e);
454            }
455        }
456    
457        public File getJbiRootDir() {
458            return jbiRootDir;
459        }
460    
461    }