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