001    /*
002     * Jpkg - Java library and tools for operating system package creation.
003     *
004     * Copyright (c) 2007 Three Rings Design, Inc.
005     * All rights reserved.
006     *
007     * Redistribution and use in source and binary forms, with or without
008     * modification, are permitted provided that the following conditions
009     * are met:
010     * 1. Redistributions of source code must retain the above copyright
011     *    notice, this list of conditions and the following disclaimer.
012     * 2. Redistributions in binary form must reproduce the above copyright
013     *    notice, this list of conditions and the following disclaimer in the
014     *    documentation and/or other materials provided with the distribution.
015     * 3. Neither the name of the copyright owner nor the names of contributors
016     *    may be used to endorse or promote products derived from this software
017     *    without specific prior written permission.
018     *
019     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
020     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
021     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
022     * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
023     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
024     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
025     * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
026     * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
027     * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
028     * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
029     * POSSIBILITY OF SUCH DAMAGE.
030     */
031    package com.threerings.jpkg.debian;
032    
033    import java.util.Enumeration;
034    import java.util.Map;
035    import java.util.TreeMap;
036    
037    import javax.mail.internet.InternetHeaders;
038    
039    import com.threerings.jpkg.PathPermissions;
040    import com.threerings.jpkg.PermissionsMap;
041    import com.threerings.jpkg.debian.dependency.DependencyAlternatives;
042    import com.threerings.jpkg.debian.dependency.PackageConflict;
043    import com.threerings.jpkg.debian.dependency.PackageConflicts;
044    import com.threerings.jpkg.debian.dependency.PackageDependencies;
045    import com.threerings.jpkg.debian.dependency.PackageDependency;
046    import com.threerings.jpkg.debian.dependency.PackageReplacement;
047    import com.threerings.jpkg.debian.dependency.PackageReplacements;
048    
049    /**
050     * Stores meta information needed to create a new Debian package.
051     * @see <a href="http://www.debian.org/doc/debian-policy/ch-controlfields.html">Debian Policy Manual</a>
052     */
053    public class PackageInfo
054    {
055        /** The default package section. */
056        public static final PackageSection DEFAULT_SECTION = new PackageSection("misc");
057    
058        /** The default package priority. */
059        public static final PackagePriority DEFAULT_PRIORITY = PackagePriority.OPTIONAL;
060    
061        /**
062         * Construct a {@link PackageInfo} object with the supplied data.
063         * Default values will be set for the package section and priority.
064         * @see PackageInfo#DEFAULT_SECTION
065         * @see PackageInfo#DEFAULT_PRIORITY
066         */
067        public PackageInfo (PackageName name, PackageVersion version, PackageArchitecture architecture,
068                            PackageMaintainer maintainer, PackageDescription description)
069        {
070            this(name, version, architecture, maintainer, description, DEFAULT_SECTION, DEFAULT_PRIORITY);
071        }
072    
073        /**
074         * Construct a fully populated {@link PackageInfo} with all required fields.
075         */
076        public PackageInfo (PackageName name, PackageVersion version, PackageArchitecture architecture,
077                            PackageMaintainer maintainer, PackageDescription description,
078                            PackageSection section, PackagePriority priority)
079        {
080            _name = name;
081            _version = version;
082            _section = section;
083            _priority = priority;
084            _architecture = architecture;
085            _maintainer = maintainer;
086            _description = description;
087    
088            assertValidFields();
089        }
090    
091        /**
092         * Add a {@link PathPermissions} object associated with a given path.
093         * @see PermissionsMap#addPathPermissions(String, PathPermissions)
094         * @throws InvalidPathException If the supplied path is invalid.
095         */
096        public void addPathPermissions (String path, PathPermissions permissions)
097        {
098            _permissions.addPathPermissions(path, permissions);
099        }
100    
101        /**
102         * Add a package dependency for this package.
103         */
104        public void addDependency (PackageDependency dependency)
105        {
106            _dependencies.addDependency(dependency);
107        }
108    
109        /**
110         * Add a dependency alternative for this package.
111         */
112        public void addDependencyAlternative (DependencyAlternatives alternative)
113        {
114            _dependencies.addAlternative(alternative);
115        }
116    
117        /**
118         * Add a package conflict for this package.
119         */
120        public void addConflict (PackageConflict conflict)
121        {
122            _conflicts.addConflict(conflict);
123        }
124    
125        /**
126         * Add a package replacement for this package.
127         */
128        public void addReplacement (PackageReplacement replacement)
129        {
130            _replacements.addReplacement(replacement);
131        }
132    
133        /**
134         * Add the defined package data to an RFC822 formatted header formatted for a Debian package
135         * control file.
136         * Order of fields determined from:
137         * <a href="http://www.debian.org/doc/debian-policy/ch-controlfields.html#s-binarycontrolfiles">Debian Policy Manual</a>
138         */
139        public InternetHeaders getControlHeaders ()
140        {
141            final InternetHeaders headers = new InternetHeaders();
142    
143            headers.addHeader(_name.getField(), _name.getFieldValue());
144            headers.addHeader(_version.getField(), _version.getFieldValue());
145    
146            headers.addHeader(_section.getField(), _section.getFieldValue());
147            headers.addHeader(_priority.getField(), _priority.getFieldValue());
148            headers.addHeader(_architecture.getField(), _architecture.getFieldValue());
149            if (_dependencies.size() > 0) {
150                headers.addHeader(_dependencies.getField(), _dependencies.getFieldValue());
151            }
152            if (_conflicts.size() > 0) {
153                headers.addHeader(_conflicts.getField(), _conflicts.getFieldValue());
154            }
155            if (_replacements.size() > 0) {
156                headers.addHeader(_replacements.getField(), _replacements.getFieldValue());
157            }
158            headers.addHeader(_maintainer.getField(), _maintainer.getFieldValue());
159            headers.addHeader(_description.getField(), _description.getFieldValue());
160    
161            return headers;
162        }
163    
164        /**
165         * Return the PermissionsMap modifying the package referred to by this PackageInfo.
166         */
167        public PermissionsMap getPermissionsMap ()
168        {
169            return _permissions;
170        }
171    
172        /**
173         * Sets a maintainer script for this package, replacing any existing script for that type.
174         */
175        public void setMaintainerScript (MaintainerScript script)
176        {
177            _scripts.put(script.getType(), script);
178        }
179    
180        /**
181         * Returns the MaintainerScripts defined for this package.
182         */
183        public Map<MaintainerScript.Type, MaintainerScript> getMaintainerScripts ()
184        {
185            return _scripts;
186        }
187    
188        @Override // from Object
189        public String toString ()
190        {
191            final StringBuilder builder = new StringBuilder();
192            @SuppressWarnings("unchecked")
193            final
194            Enumeration<String> en = getControlHeaders().getAllHeaderLines();
195            while (en.hasMoreElements())
196            {
197                builder.append(en.nextElement()).append("\n");
198            }
199            return builder.toString();
200        }
201    
202        /**
203         * Validates that none of the required fields were null.
204         */
205        private void assertValidFields ()
206        {
207            if (_name == null) throw new IllegalArgumentException("The PackageName cannot be null.");
208            if (_version == null) throw new IllegalArgumentException("The PackageVersion cannot be null.");
209            if (_section == null) throw new IllegalArgumentException("The PackageSection cannot be null.");
210            if (_priority == null) throw new IllegalArgumentException("The PackagePriority cannot be null.");
211            if (_architecture == null) throw new IllegalArgumentException("The PackageArchitecture cannot be null.");
212            if (_maintainer == null) throw new IllegalArgumentException("The PackageMaintainer cannot be null.");
213            if (_description == null) throw new IllegalArgumentException("The PackageDescription cannot be null.");
214        }
215    
216        /** The package name. */
217        private final PackageName _name;
218    
219        /** The package version. */
220        private final PackageVersion _version;
221    
222        /** The package section, e.g. "web". */
223        private final PackageSection _section;
224    
225        /** The package priority, e.g. "optional". */
226        private final PackagePriority _priority;
227    
228        /** The package architecture, e.g. "i386". */
229        private final PackageArchitecture _architecture;
230    
231        /** A list of packages this package depends on. */
232        private final PackageDependencies _dependencies = new PackageDependencies();
233    
234        /** A list of packages this package conflicts with. */
235        private final PackageConflicts _conflicts = new PackageConflicts();
236    
237        /** A list of packages this package replaces. */
238        private final PackageReplacements _replacements = new PackageReplacements();
239    
240        /** Permissions to apply to paths contained within this package. */
241        private final PermissionsMap _permissions = new PermissionsMap();
242    
243        /** The package maintainer, e.g. "Package maintainer &lt;maintainer@corp.com&gt;". */
244        private final PackageMaintainer _maintainer;
245    
246        /** A description for this package. */
247        private final PackageDescription _description;
248    
249        /** The maintainer scripts to run with this package. */
250        private final Map<MaintainerScript.Type, MaintainerScript> _scripts =
251            new TreeMap<MaintainerScript.Type, MaintainerScript>();
252    }