001/*
002 * (C) Copyright 2006-2018 Nuxeo (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.xml;
022
023import org.apache.commons.lang3.mutable.MutableObject;
024import org.nuxeo.common.xmap.annotation.XNode;
025import org.nuxeo.common.xmap.annotation.XNodeList;
026import org.nuxeo.common.xmap.annotation.XObject;
027import org.nuxeo.connect.data.PackageDescriptor;
028import org.nuxeo.connect.update.PackageDependency;
029import org.nuxeo.connect.update.PackageState;
030import org.nuxeo.connect.update.PackageType;
031import org.nuxeo.connect.update.Validator;
032import org.nuxeo.connect.update.Version;
033import org.nuxeo.connect.update.model.PackageDefinition;
034import org.nuxeo.connect.update.model.TaskDefinition;
035import org.nuxeo.connect.update.task.Task;
036
037/**
038 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
039 */
040@XObject("package")
041public class PackageDefinitionImpl implements PackageDefinition {
042
043    @XNode("@name")
044    protected String name;
045
046    @XNode("@version")
047    protected Version version;
048
049    @XNode("@type")
050    protected PackageType type;
051
052    @XNode("title")
053    protected String title;
054
055    @XNode("description")
056    protected String description;
057
058    @XNode("classifier")
059    protected String classifier;
060
061    @XNode("vendor")
062    protected String vendor;
063
064    @XNode("hotreload-support")
065    protected boolean hotReloadSupport = false;
066
067    @XNode("require-terms-and-conditions-acceptance")
068    protected boolean requireTermsAndConditionsAcceptance = false;
069
070    /**
071     * The license name. E.g. LGPL, BSD etc.
072     */
073    @XNode("license")
074    protected String license;
075
076    /**
077     * A license URL. If no specified the license.txt file in the package is the license content
078     */
079    @XNode("license-url")
080    protected String licenseUrl;
081
082    /**
083     * The target platforms where this package may be installed.
084     */
085    protected String[] platforms;
086
087    /**
088     * The target platform range where this package may be installed.
089     *
090     * @since 11.4
091     */
092    @XNode("target-platform/version")
093    protected String targetPlatformRange;
094
095    /**
096     * The target platform name where this package may be installed.
097     *
098     * @since 11.4
099     */
100    @XNode("target-platform/name")
101    protected String targetPlatformName;
102
103    /**
104     * The dependency value format is: <code>package_name[:package_min_version[:package_max_version]]</code> if no min
105     * and max version are specified the the last version should be used.
106     */
107    @XNodeList(value = "dependencies/package", type = PackageDependency[].class, componentType = PackageDependency.class)
108    protected PackageDependency[] dependencies;
109
110    /**
111     * The optional dependencies are defined for ordering purpose, to make sure that if they are being installed along
112     * with the current package, they will be ordered first.
113     */
114    @XNodeList(value = "optional-dependencies/package", type = PackageDependency[].class, componentType = PackageDependency.class)
115    protected PackageDependency[] optionalDependencies;
116
117    /**
118     * The conflict value format is: <code>package_name[:package_min_version[:package_max_version]]</code> if no min and
119     * max version are specified the the last version should be used.
120     */
121    @XNodeList(value = "conflicts/package", type = PackageDependency[].class, componentType = PackageDependency.class)
122    protected PackageDependency[] conflicts;
123
124    /**
125     * The provides value format is: <code>package_name[:package_min_version[:package_max_version]]</code> if no min and
126     * max version are specified the the last version should be used.
127     */
128    @XNodeList(value = "provides/package", type = PackageDependency[].class, componentType = PackageDependency.class)
129    protected PackageDependency[] provides;
130
131    /**
132     * A class implementing {@link Task}. if not specified the default implementation will be used
133     */
134    @XNode("installer")
135    protected TaskDefinitionImpl installer;
136
137    /**
138     * A class implementing {@link Task}. if not specified the default implementation will be used
139     */
140    @XNode("uninstaller")
141    protected TaskDefinitionImpl uninstaller;
142
143    /**
144     * A class implementing {@link Validator}. If not specified not post install validation will be done
145     */
146    @XNode("validator")
147    protected String validator;
148
149    @Override
150    public String getId() {
151        if (version == null) {
152            return name;
153        } else {
154            return name + "-" + version.toString();
155        }
156    }
157
158    @Override
159    public String getName() {
160        return name;
161    }
162
163    @Override
164    public void setName(String name) {
165        this.name = name;
166        dependencies = PackageDescriptor.fixDependencies(name, dependencies);
167    }
168
169    @Override
170    public Version getVersion() {
171        return version;
172    }
173
174    @Override
175    public void setVersion(Version version) {
176        this.version = version;
177    }
178
179    @Override
180    public String getTitle() {
181        return title;
182    }
183
184    @Override
185    public void setTitle(String title) {
186        this.title = title;
187    }
188
189    @Override
190    public String getDescription() {
191        return description;
192    }
193
194    @Override
195    public void setDescription(String description) {
196        this.description = description;
197    }
198
199    @Override
200    public PackageType getType() {
201        return type;
202    }
203
204    @Override
205    public void setType(PackageType type) {
206        this.type = type;
207    }
208
209    @Override
210    public String getClassifier() {
211        return classifier;
212    }
213
214    @Override
215    public void setClassifier(String classifier) {
216        this.classifier = classifier;
217    }
218
219    @Deprecated
220    @Override
221    public String getLicense() {
222        return getLicenseType();
223    }
224
225    @Override
226    public String getLicenseType() {
227        return license;
228    }
229
230    @Deprecated
231    @Override
232    public void setLicense(String license) {
233        setLicenseType(license);
234    }
235
236    @Override
237    public void setLicenseType(String license) {
238        this.license = license;
239    }
240
241    @Override
242    public String getLicenseUrl() {
243        return licenseUrl;
244    }
245
246    @Override
247    public void setLicenseUrl(String licenseUrl) {
248        this.licenseUrl = licenseUrl;
249    }
250
251    @Deprecated
252    @Override
253    public String[] getPlatforms() {
254        return getTargetPlatforms();
255    }
256
257    @Override
258    public String[] getTargetPlatforms() {
259        return platforms;
260    }
261
262    @Deprecated
263    @Override
264    public void setPlatforms(String[] platforms) {
265        setTargetPlatforms(platforms);
266    }
267
268    @XNodeList(value = "platforms/platform", type = String[].class, componentType = String.class)
269    @Override
270    public void setTargetPlatforms(String[] platforms) {
271        MutableObject<?> packageDependencies = new MutableObject<>();
272        this.platforms = PackageDescriptor.fixTargetPlatforms(name, platforms, packageDependencies);
273        setDependencies((PackageDependency[]) packageDependencies.getValue());
274    }
275
276    @Override
277    public String getTargetPlatformRange() {
278        return targetPlatformRange;
279    }
280
281    @Override
282    public void setTargetPlatformRange(String targetPlatformRange) {
283        this.targetPlatformRange = targetPlatformRange;
284    }
285
286    @Override
287    public String getTargetPlatformName() {
288        return targetPlatformName;
289    }
290
291    @Override
292    public void setTargetPlatformName(String targetPlatformName) {
293        this.targetPlatformName = targetPlatformName;
294    }
295
296    @Override
297    public PackageDependency[] getDependencies() {
298        return dependencies;
299    }
300
301    @Override
302    public void setDependencies(PackageDependency[] dependencies) {
303        this.dependencies = PackageDescriptor.addPackageDependencies(this.dependencies, dependencies);
304    }
305
306    @Override
307    public PackageDependency[] getOptionalDependencies() {
308        return optionalDependencies;
309    }
310
311    @Override
312    public void setOptionalDependencies(PackageDependency[] optionalDependencies) {
313        this.optionalDependencies = optionalDependencies;
314    }
315
316    @Override
317    public PackageDependency[] getConflicts() {
318        return conflicts;
319    }
320
321    @Override
322    public void setConflicts(PackageDependency[] conflicts) {
323        this.conflicts = conflicts;
324    }
325
326    @Override
327    public PackageDependency[] getProvides() {
328        return provides;
329    }
330
331    @Override
332    public void setProvides(PackageDependency[] provides) {
333        this.provides = provides;
334    }
335
336    @Override
337    public String getVendor() {
338        return vendor;
339    }
340
341    @Override
342    public void setVendor(String vendor) {
343        this.vendor = vendor;
344    }
345
346    @Override
347    public TaskDefinition getInstaller() {
348        return installer;
349    }
350
351    @Override
352    public void setInstaller(TaskDefinition installer) {
353        if (installer instanceof TaskDefinitionImpl) {
354            this.installer = (TaskDefinitionImpl) installer;
355        } else {
356            this.installer = new TaskDefinitionImpl(installer.getType(), installer.getRequireRestart());
357        }
358    }
359
360    @Override
361    public TaskDefinition getUninstaller() {
362        return uninstaller;
363    }
364
365    @Override
366    public void setUninstaller(TaskDefinition uninstaller) {
367        if (uninstaller instanceof TaskDefinitionImpl) {
368            this.uninstaller = (TaskDefinitionImpl) uninstaller;
369        } else {
370            this.uninstaller = new TaskDefinitionImpl(uninstaller.getType(), uninstaller.getRequireRestart());
371        }
372    }
373
374    @Override
375    public String getValidator() {
376        return validator;
377    }
378
379    @Override
380    public void setValidator(String validator) {
381        this.validator = validator;
382    }
383
384    @Override
385    public void setHotReloadSupport(boolean hotReloadSupport) {
386        this.hotReloadSupport = hotReloadSupport;
387    }
388
389    @Deprecated
390    public void write(XmlWriter writer) {
391        writer.writeXmlDecl();
392
393        writer.start("package");
394        writer.attr("name", name);
395        if (version != null) {
396            writer.attr("version", version.toString());
397        }
398        if (type != null) {
399            writer.attr("type", type.getValue());
400        }
401        writer.startContent();
402        writer.element("title", title);
403        writer.element("description", description);
404        writer.element("classifier", classifier);
405        writer.element("vendor", vendor);
406        writer.element("license", license);
407        writer.element("license-url", licenseUrl);
408        writer.element("hotreload-support", Boolean.valueOf(hotReloadSupport).toString());
409        writer.element("require-terms-and-conditions-acceptance",
410                Boolean.valueOf(requireTermsAndConditionsAcceptance).toString());
411        if (platforms != null) {
412            writer.start("platforms");
413            writer.startContent();
414            for (String platform : platforms) {
415                writer.element("platform", platform);
416            }
417            writer.end("platforms");
418        }
419        if (dependencies != null) {
420            writer.start("dependencies");
421            writer.startContent();
422            for (PackageDependency dep : dependencies) {
423                writer.element("package", dep.toString());
424            }
425            writer.end("dependencies");
426        }
427
428        if (optionalDependencies != null) {
429            writer.start("optional-dependencies");
430            writer.startContent();
431            for (PackageDependency dep : optionalDependencies) {
432                writer.element("package", dep.toString());
433            }
434            writer.end("optional-dependencies");
435        }
436
437        if (installer != null) {
438            writer.start("installer");
439            writer.attr("class", installer.getType());
440            writer.attr("restart", String.valueOf(installer.getRequireRestart()));
441            writer.end();
442        }
443        if (uninstaller != null) {
444            writer.start("uninstaller");
445            writer.attr("class", uninstaller.getType());
446            writer.attr("restart", String.valueOf(uninstaller.getRequireRestart()));
447            writer.end();
448        }
449        writer.element("validator", validator);
450        writer.end("package");
451    }
452
453    @Override
454    public boolean supportsHotReload() {
455        return hotReloadSupport;
456    }
457
458    @Override
459    public void setRequireTermsAndConditionsAcceptance(boolean requireTermsAndConditionsAcceptance) {
460        this.requireTermsAndConditionsAcceptance = requireTermsAndConditionsAcceptance;
461    }
462
463    @Override
464    public boolean requireTermsAndConditionsAcceptance() {
465        return requireTermsAndConditionsAcceptance;
466    }
467
468    @Override
469    public String toXML() {
470        return new XmlSerializer().toXML(this);
471    }
472
473    @Deprecated
474    @Override
475    public int getState() {
476        return PackageState.UNKNOWN.getValue();
477    }
478
479    @Override
480    public PackageState getPackageState() {
481        return PackageState.UNKNOWN;
482    }
483
484    @Override
485    public boolean isLocal() {
486        throw new UnsupportedOperationException();
487    }
488}