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.framework;
018    
019    import java.io.File;
020    import java.util.ArrayList;
021    import java.util.Arrays;
022    import java.util.Collections;
023    import java.util.Iterator;
024    import java.util.List;
025    
026    import javax.jbi.component.ComponentContext;
027    import javax.jbi.component.InstallationContext;
028    
029    import org.w3c.dom.DocumentFragment;
030    
031    import org.apache.servicemix.jbi.deployment.Component;
032    import org.apache.servicemix.jbi.deployment.InstallationDescriptorExtension;
033    import org.apache.servicemix.jbi.deployment.SharedLibraryList;
034    
035    /**
036     * This context contains information necessary for a JBI component to perform its installation/uninstallation
037     * processing. This is provided to the init() method of the component {@link Bootstrap}interface.
038     * 
039     * @version $Revision: 564900 $
040     */
041    public class InstallationContextImpl implements InstallationContext {
042        
043        private Component descriptor;
044        private File installRoot;
045        private List<String> classPathElements = Collections.emptyList();
046        private ComponentContext context;
047        private boolean install = true;
048        
049        public InstallationContextImpl(Component descriptor) {
050            this.descriptor = descriptor;
051            if (descriptor.getComponentClassPath() != null
052                    && descriptor.getComponentClassPath().getPathElements() != null
053                    && descriptor.getComponentClassPath().getPathElements().length > 0) {
054                String[] elems = descriptor.getComponentClassPath().getPathElements();
055                for (int i = 0; i < elems.length; i++) {
056                    if (File.separatorChar == '\\') {
057                        elems[i] = elems[i].replace('/', '\\');
058                    } else {
059                        elems[i] = elems[i].replace('\\', '/');
060                    }
061                }
062                setClassPathElements(Arrays.asList(elems));
063            }
064        }
065    
066        /**
067         * @return the descriptor
068         */
069        public Component getDescriptor() {
070            return descriptor;
071        }
072    
073        /**
074         * @return the sharedLibraries
075         */
076        public String[] getSharedLibraries() {
077            return getSharedLibraries(descriptor.getSharedLibraries());
078        }
079    
080        /**
081         * Get the name of the class that implements the {@link Component}interface for this component. This must be the
082         * component class name given in the component's installation descriptor.
083         * 
084         * @return the {@link Component}implementation class name, which must be non-null and non-empty.
085         */
086        public String getComponentClassName() {
087            return descriptor.getComponentClassName();
088        }
089    
090        /**
091         * Get a list of elements that comprise the class path for this component. Each element represents either a
092         * directory (containing class files) or a library file. All elements are reachable from the install root. These
093         * elements represent class path items that the component's execution-time component class loader uses, in search
094         * order. All path elements must use the file separator character appropriate to the system (i.e.,
095         * <code>File.separator</code>).
096         * 
097         * @return a list of String objects, each of which contains a class path elements. The list must contain at least
098         * one class path element.
099         */
100        public List getClassPathElements() {
101            return classPathElements;
102        }
103    
104        /**
105         * Get the unique name assigned to this component. This name must be assigned from the component's installation
106         * descriptor identification section.
107         * 
108         * @return the unique component name, which must be non-null and non-empty.
109         */
110        public String getComponentName() {
111            return descriptor.getIdentification().getName();
112        }
113    
114        /**
115         * Get the JBI context for this component. The following methods are valid to use on the context:
116         * <ul>
117         * <li>{@link ComponentContext#getMBeanNames()}</li>
118         * <li>{@link ComponentContext#getMBeanServer()}</li>
119         * <li>{@link ComponentContext#getNamingContext()}</li>
120         * <li>{@link ComponentContext#getTransactionManager()}</li>
121         * </ul>
122         * All other methods on the returned context must throw a <code>IllegalStateException</code> exception if invoked.
123         * 
124         * @return the JBI context for this component, which must be non-null.
125         */
126        public ComponentContext getContext() {
127            return context;
128        }
129    
130        /**
131         * Get the installation root directory full path name for this component. This path name must be formatted for the
132         * platform the JBI environment is running on.
133         * 
134         * @return the installation root directory name, which must be non-null and non-empty.
135         */
136        public String getInstallRoot() {
137            return installRoot != null ? installRoot.getAbsolutePath() : ".";
138        }
139        
140        /**
141         * 
142         * @return Return the install root
143         */
144        public File getInstallRootAsDir() {
145            return installRoot;
146        }
147    
148        /**
149         * Return a DOM document fragment representing the installation descriptor (jbi.xml) extension data for the
150         * component, if any.
151         * <p>
152         * The Installation Descriptor Extension data are located at the end of the &lt;component&gt; element of the
153         * installation descriptor.
154         * 
155         * @return a DOM document fragment containing the installation descriptor (jbi.xml) extension data, or
156         * <code>null</code> if none is present in the descriptor.
157         */
158        public DocumentFragment getInstallationDescriptorExtension() {
159            InstallationDescriptorExtension desc = descriptor.getDescriptorExtension();
160            return desc != null ? desc.getDescriptorExtension() : null;
161        }
162    
163        /**
164         * Returns <code>true</code> if this context was created in order to install a component into the JBI environment.
165         * Returns <code>false</code> if this context was created to uninstall a previously installed component.
166         * <p>
167         * This method is provided to allow {@link Bootstrap}implementations to tailor their behaviour according to use
168         * case. For example, the {@link Bootstrap#init(InstallationContext)}method implementation may create different
169         * types of extension MBeans, depending on the use case specified by this method.
170         * 
171         * @return <code>true</code> if this context was created in order to install a component into the JBI environment;
172         * otherwise the context was created to uninstall an existing component.
173         */
174        public boolean isInstall() {
175            return install;
176        }
177    
178        /**
179         * Set the list of elements that comprise the class path for this component. Each element represents either a
180         * directory (containing class files) or a library file. Elements are reached from the install root. These elements
181         * represent class path items that the component's execution-time component class loader uses, in search order. All
182         * file paths are relative to the install root of the component.
183         * <p>
184         * This method allows the component's bootstrap to alter the execution-time class path specified by the component's
185         * installation descriptor. The component configuration determined during installation can affect the class path
186         * needed by the component at execution-time. All path elements must use the file separator character appropriate to
187         * the system (i.e., <code>File.separator</code>.
188         * 
189         * @param classPathElements a list of String objects, each of which contains a class path elements; the list must be
190         * non-null and contain at least one class path element.
191         * @exception IllegalArgumentException if the class path elements is null, empty, or if an individual element is
192         * ill-formed.
193         */
194        public final void setClassPathElements(List classPathElements) {
195            if (classPathElements == null) {
196                throw new IllegalArgumentException("classPathElements is null");
197            }
198            if (classPathElements.isEmpty()) {
199                throw new IllegalArgumentException("classPathElements is empty");
200            }
201            for (Iterator iter = classPathElements.iterator(); iter.hasNext();) {
202                Object obj = iter.next();
203                if (!(obj instanceof String)) {
204                    throw new IllegalArgumentException("classPathElements must contain element of type String");
205                }
206                String element = (String) obj;
207                String sep = "\\".equals(File.separator) ? "/" : "\\";
208                int offset = element.indexOf(sep);
209                if (offset > -1) {
210                    throw new IllegalArgumentException("classPathElements contains an invalid file separator '" + sep + "'"); 
211                }
212                File f = new File((String) element);
213                if (f.isAbsolute()) {
214                    throw new IllegalArgumentException("classPathElements should not contain absolute paths");
215                }
216            }
217            this.classPathElements = new ArrayList<String>(classPathElements);
218        }
219        
220        
221        /**
222         * @param context The context to set.
223         */
224        public void setContext(ComponentContext context) {
225            this.context = context;
226        }
227        /**
228         * @param install The install to set.
229         */
230        public void setInstall(boolean install) {
231            this.install = install;
232        }
233        /**
234         * @param installRoot The installRoot to set.
235         */
236        public void setInstallRoot(File installRoot) {
237            this.installRoot = installRoot;
238        }
239        /**
240         * @return Returns the binding.
241         */
242        public boolean isBinding() {
243            return descriptor.isBindingComponent();
244        }
245        /**
246         * @return Returns the engine.
247         */
248        public boolean isEngine() {
249            return descriptor.isServiceEngine();
250        }
251        /**
252         * @return Returns the componentDescription.
253         */
254        public String getComponentDescription() {
255            return descriptor.getIdentification().getDescription();
256        }
257    
258        private static String[] getSharedLibraries(SharedLibraryList[] sharedLibraries) {
259            if (sharedLibraries == null || sharedLibraries.length == 0) {
260                return null;
261            }
262            String[] names = new String[sharedLibraries.length];
263            for (int i = 0; i < names.length; i++) {
264                names[i] = sharedLibraries[i].getName();
265            }
266            return names;
267        }
268    
269    }