001/*
002 * (C) Copyright 2006-2016 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     bstefanescu
018 *     jcarsique
019 *     Yannis JULIENNE
020 */
021package org.nuxeo.connect.update.standalone;
022
023import java.io.File;
024import java.io.FileInputStream;
025import java.io.FileNotFoundException;
026import java.io.IOException;
027import java.io.InputStream;
028
029import org.nuxeo.common.utils.FileUtils;
030import org.nuxeo.common.xmap.XMap;
031import org.nuxeo.connect.update.LocalPackage;
032import org.nuxeo.connect.update.NuxeoValidationState;
033import org.nuxeo.connect.update.PackageDependency;
034import org.nuxeo.connect.update.PackageException;
035import org.nuxeo.connect.update.PackageState;
036import org.nuxeo.connect.update.PackageType;
037import org.nuxeo.connect.update.PackageUpdateService;
038import org.nuxeo.connect.update.PackageVisibility;
039import org.nuxeo.connect.update.ProductionState;
040import org.nuxeo.connect.update.Validator;
041import org.nuxeo.connect.update.Version;
042import org.nuxeo.connect.update.model.Form;
043import org.nuxeo.connect.update.model.TaskDefinition;
044import org.nuxeo.connect.update.task.Task;
045import org.nuxeo.connect.update.xml.FormsDefinition;
046import org.nuxeo.connect.update.xml.PackageDefinitionImpl;
047import org.nuxeo.connect.update.xml.TaskDefinitionImpl;
048
049/**
050 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
051 */
052public class LocalPackageImpl implements LocalPackage {
053
054    protected String id;
055
056    protected PackageState state = PackageState.UNKNOWN;
057
058    protected LocalPackageData data;
059
060    protected PackageDefinitionImpl def;
061
062    private PackageUpdateService service;
063
064    /**
065     * @deprecated Since 5.8. Use {@link #LocalPackageImpl(File, PackageState, PackageUpdateService)} instead.
066     */
067    @Deprecated
068    public LocalPackageImpl(File file, int state, PackageUpdateService pus) throws PackageException {
069        this(null, file, state, pus);
070    }
071
072    /**
073     * @deprecated Since 5.8. Use {@link #LocalPackageImpl(ClassLoader, File, PackageState, PackageUpdateService)}
074     *             instead.
075     */
076    @Deprecated
077    public LocalPackageImpl(ClassLoader parent, File file, int state, PackageUpdateService pus) throws PackageException {
078        this(parent, file, PackageState.getByValue(state), pus);
079    }
080
081    /**
082     * @since 5.7
083     */
084    public LocalPackageImpl(File file, PackageState state, PackageUpdateService pus) throws PackageException {
085        this(null, file, state, pus);
086    }
087
088    /**
089     * @since 5.8
090     */
091    public LocalPackageImpl(ClassLoader parent, File file, PackageState state, PackageUpdateService pus)
092            throws PackageException {
093        this.state = state;
094        service = pus;
095        XMap xmap = StandaloneUpdateService.getXmap();
096        if (xmap == null) { // for tests
097            xmap = StandaloneUpdateService.createXmap();
098        }
099        try {
100            data = new LocalPackageData(parent, file);
101            InputStream in = new FileInputStream(data.getManifest());
102            def = (PackageDefinitionImpl) xmap.load(in);
103        } catch (FileNotFoundException e) {
104            throw new PackageException("Invalid package - no package.xml file found in package " + file.getName());
105        } catch (IOException e) {
106            throw new PackageException("Failed to load package.xml descriptor for package " + file.getName(), e);
107        }
108        id = def.getId();
109    }
110
111    @Deprecated
112    @Override
113    public void setState(int state) {
114        this.state = PackageState.getByValue(state);
115    }
116
117    @Override
118    public void setState(PackageState state) {
119        this.state = state;
120    }
121
122    @Override
123    public LocalPackageData getData() {
124        return data;
125    }
126
127    @Override
128    public File getInstallFile() throws PackageException {
129        return data.getEntry(LocalPackage.INSTALL);
130    }
131
132    @Override
133    public File getUninstallFile() throws PackageException {
134        return data.getEntry(LocalPackage.UNINSTALL);
135    }
136
137    @Override
138    public String getLicenseType() {
139        return def.getLicenseType();
140    }
141
142    @Override
143    public String getLicenseUrl() {
144        return def.getLicenseUrl();
145    }
146
147    @Override
148    public String getLicenseContent() throws PackageException {
149        File file = data.getEntry(LocalPackage.LICENSE);
150        if (file.isFile()) {
151            try {
152                return FileUtils.readFile(file);
153            } catch (IOException e) {
154                throw new PackageException("Failed to read license.txt file for package: " + getId());
155            }
156        }
157        return null;
158    }
159
160    @Override
161    public String getClassifier() {
162        return def.getClassifier();
163    }
164
165    @Override
166    public String getDescription() {
167        return def.getDescription();
168    }
169
170    @Override
171    public String getId() {
172        return id;
173    }
174
175    @Override
176    public String getName() {
177        return def.getName();
178    }
179
180    @Override
181    public String getTitle() {
182        return def.getTitle();
183    }
184
185    @Deprecated
186    @Override
187    public int getState() {
188        return state.getValue();
189    }
190
191    @Override
192    public PackageState getPackageState() {
193        return state;
194    }
195
196    @Override
197    public String[] getTargetPlatforms() {
198        return def.getTargetPlatforms();
199    }
200
201    @Override
202    public PackageDependency[] getDependencies() {
203        return def.getDependencies();
204    }
205
206    @Override
207    public PackageDependency[] getOptionalDependencies() {
208        return def.getOptionalDependencies();
209    }
210
211    @Override
212    public PackageDependency[] getConflicts() {
213        return def.getConflicts();
214    }
215
216    @Override
217    public PackageDependency[] getProvides() {
218        return def.getProvides();
219    }
220
221    @Override
222    public PackageType getType() {
223        return def.getType();
224    }
225
226    @Override
227    public String getHomePage() {
228        return def.getHomePage();
229    }
230
231    @Override
232    public Version getVersion() {
233        return def.getVersion();
234    }
235
236    @Override
237    public String getVendor() {
238        return def.getVendor();
239    }
240
241    @Override
242    public boolean isLocal() {
243        return true;
244    }
245
246    @Override
247    public Task getInstallTask() throws PackageException {
248        if (def.getInstaller() == null) {
249            def.setInstaller(new TaskDefinitionImpl(service.getDefaultInstallTaskType(), false));
250        } else if (def.getInstaller().getType() == null) {
251            def.getInstaller().setType(service.getDefaultInstallTaskType());
252        }
253        return getTask(def.getInstaller());
254    }
255
256    @Override
257    public Task getUninstallTask() throws PackageException {
258        if (def.getUninstaller() == null) {
259            def.setUninstaller(new TaskDefinitionImpl(service.getDefaultUninstallTaskType(), false));
260        } else if (def.getUninstaller().getType() == null) {
261            def.getUninstaller().setType(service.getDefaultUninstallTaskType());
262        }
263        return getTask(def.getUninstaller());
264    }
265
266    protected Task getTask(TaskDefinition tdef) throws PackageException {
267        Task task = null;
268        try {
269            task = (Task) data.loadClass(tdef.getType()).getConstructor(PackageUpdateService.class).newInstance(service);
270        } catch (ReflectiveOperationException e) {
271            throw new PackageException("Could not instantiate custom task " + tdef.getType() + " for package "
272                    + getId(), e);
273        }
274        task.initialize(this, tdef.getRequireRestart());
275        return task;
276    }
277
278    @Override
279    public Validator getValidator() throws PackageException {
280        if (def.getValidator() != null) {
281            try {
282                return (Validator) data.loadClass(def.getValidator()).getConstructor().newInstance();
283            } catch (ReflectiveOperationException e) {
284                throw new PackageException("Could not instantiate custom validator " + def.getValidator()
285                        + " for package " + getId(), e);
286            }
287        }
288        return null;
289    }
290
291    public Form[] getForms(String path) throws PackageException {
292        File file = data.getEntry(path);
293        if (file.isFile()) {
294            FileInputStream in = null;
295            try {
296                in = new FileInputStream(file);
297                FormsDefinition forms = (FormsDefinition) StandaloneUpdateService.getXmap().load(in);
298                return forms.getForms();
299            } catch (IOException e) {
300                throw new PackageException("Failed to load forms file: " + file);
301            } finally {
302                if (in != null) {
303                    try {
304                        in.close();
305                    } catch (IOException e) {
306                    }
307                }
308            }
309        }
310        return null;
311    }
312
313    @Override
314    public Form[] getValidationForms() throws PackageException {
315        return getForms(LocalPackage.VALIDATION_FORMS);
316    }
317
318    @Override
319    public Form[] getInstallForms() throws PackageException {
320        return getForms(LocalPackage.INSTALL_FORMS);
321    }
322
323    @Override
324    public Form[] getUninstallForms() throws PackageException {
325        return getForms(LocalPackage.UNINSTALL_FORMS);
326    }
327
328    @Override
329    public String getTermsAndConditionsContent() throws PackageException {
330        File file = data.getEntry(LocalPackage.TERMSANDCONDITIONS);
331        if (file.isFile()) {
332            try {
333                return FileUtils.readFile(file);
334            } catch (IOException e) {
335                throw new PackageException("Failed to read license.txt file for package: " + getId());
336            }
337        }
338        return null;
339    }
340
341    @Override
342    public boolean requireTermsAndConditionsAcceptance() {
343        return def.requireTermsAndConditionsAcceptance();
344    }
345
346    @Override
347    public ProductionState getProductionState() {
348        return def.getProductionState();
349    }
350
351    @Override
352    public NuxeoValidationState getValidationState() {
353        return def.getValidationState();
354    }
355
356    @Override
357    public boolean isSupported() {
358        return def.isSupported();
359    }
360
361    @Override
362    public boolean supportsHotReload() {
363        return def.supportsHotReload();
364    }
365
366    @Override
367    public PackageVisibility getVisibility() {
368        return def.getVisibility();
369    }
370
371    @Override
372    public String toString() {
373        return getId();
374    }
375
376}