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