Tue, 10 Feb 2015 18:12:00 +0100
Import initial revisions of existing project AndroidCaldavSyncAdapater,
forked from upstream repository at 27e8a0f8495c92e0780d450bdf0c7cec77a03a55.
1 /**
2 * Copyright (c) 2012, Ben Fortuna
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * o Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * o Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * o Neither the name of Ben Fortuna nor the names of any other contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32 package net.fortuna.ical4j.model.property;
34 import java.io.IOException;
35 import java.io.UnsupportedEncodingException;
36 import java.net.URI;
37 import java.net.URISyntaxException;
39 import net.fortuna.ical4j.model.Parameter;
40 import net.fortuna.ical4j.model.ParameterList;
41 import net.fortuna.ical4j.model.Property;
42 import net.fortuna.ical4j.model.PropertyFactoryImpl;
43 import net.fortuna.ical4j.model.ValidationException;
44 import net.fortuna.ical4j.model.parameter.Encoding;
45 import net.fortuna.ical4j.model.parameter.Value;
46 import net.fortuna.ical4j.util.DecoderFactory;
47 import net.fortuna.ical4j.util.EncoderFactory;
48 import net.fortuna.ical4j.util.ParameterValidator;
49 import net.fortuna.ical4j.util.Strings;
50 import net.fortuna.ical4j.util.Uris;
52 import org.apache.commons.codec.BinaryDecoder;
53 import org.apache.commons.codec.BinaryEncoder;
54 import org.apache.commons.codec.DecoderException;
55 import org.apache.commons.codec.EncoderException;
56 import org.apache.commons.logging.Log;
57 import org.apache.commons.logging.LogFactory;
59 /**
60 * $Id$
61 *
62 * Created: [Apr 6, 2004]
63 *
64 * Defines an ATTACH iCalendar component property.
65 *
66 * <pre>
67 * 4.8.1.1 Attachment
68 *
69 * Property Name: ATTACH
70 *
71 * Purpose: The property provides the capability to associate a document
72 * object with a calendar component.
73 *
74 * Value Type: The default value type for this property is URI. The
75 * value type can also be set to BINARY to indicate inline binary
76 * encoded content information.
77 *
78 * Property Parameters: Non-standard, inline encoding, format type and
79 * value data type property parameters can be specified on this
80 * property.
81 *
82 * Conformance: The property can be specified in a "VEVENT", "VTODO",
83 * "VJOURNAL" or "VALARM" calendar components.
84 *
85 * Description: The property can be specified within "VEVENT", "VTODO",
86 * "VJOURNAL", or "VALARM" calendar components. This property can be
87 * specified multiple times within an iCalendar object.
88 *
89 * Format Definition: The property is defined by the following notation:
90 *
91 * attach = "ATTACH" attparam ":" uri CRLF
92 *
93 * attach =/ "ATTACH" attparam ";" "ENCODING" "=" "BASE64"
94 * ";" "VALUE" "=" "BINARY" ":" binary
95 *
96 * attparam = *(
97 *
98 * ; the following is optional,
99 * ; but MUST NOT occur more than once
100 *
101 * (";" fmttypeparam) /
102 *
103 * ; the following is optional,
104 * ; and MAY occur more than once
105 *
106 * (";" xparam)
107 *
108 * )
109 * </pre>
110 *
111 * @author benf
112 */
113 public class Attach extends Property {
115 private static final long serialVersionUID = 4439949507756383452L;
117 private URI uri;
119 private byte[] binary;
121 /**
122 * Default constructor.
123 */
124 public Attach() {
125 super(ATTACH, PropertyFactoryImpl.getInstance());
126 }
128 /**
129 * @param aList a list of parameters for this component
130 * @param aValue a value string for this component
131 * @throws IOException when there is an error reading the binary stream
132 * @throws URISyntaxException where the specified string is not a valid uri
133 */
134 public Attach(final ParameterList aList, final String aValue)
135 throws IOException, URISyntaxException {
136 super(ATTACH, aList, PropertyFactoryImpl.getInstance());
137 setValue(aValue);
138 }
140 /**
141 * @param data binary data
142 */
143 public Attach(final byte[] data) {
144 super(ATTACH, PropertyFactoryImpl.getInstance());
145 // add required parameters..
146 getParameters().add(Encoding.BASE64);
147 getParameters().add(Value.BINARY);
148 this.binary = data;
149 }
151 /**
152 * @param aList a list of parameters for this component
153 * @param data binary data
154 */
155 public Attach(final ParameterList aList, final byte[] data) {
156 super(ATTACH, aList, PropertyFactoryImpl.getInstance());
157 this.binary = data;
158 }
160 /**
161 * @param aUri a URI
162 */
163 public Attach(final URI aUri) {
164 super(ATTACH, PropertyFactoryImpl.getInstance());
165 this.uri = aUri;
166 }
168 /**
169 * @param aList a list of parameters for this component
170 * @param aUri a URI
171 */
172 public Attach(final ParameterList aList, final URI aUri) {
173 super(ATTACH, aList, PropertyFactoryImpl.getInstance());
174 this.uri = aUri;
175 }
177 /**
178 * {@inheritDoc}
179 */
180 public final void validate() throws ValidationException {
182 /*
183 * ; the following is optional, ; but MUST NOT occur more than once (";" fmttypeparam) /
184 */
185 ParameterValidator.getInstance().assertOneOrLess(Parameter.FMTTYPE,
186 getParameters());
188 /*
189 * ; the following is optional, ; and MAY occur more than once (";" xparam)
190 */
192 /*
193 * If the value type parameter is ";VALUE=BINARY", then the inline encoding parameter MUST be specified with the
194 * value ";ENCODING=BASE64".
195 */
196 if (Value.BINARY.equals(getParameter(Parameter.VALUE))) {
197 ParameterValidator.getInstance().assertOne(Parameter.ENCODING,
198 getParameters());
199 if (!Encoding.BASE64.equals(getParameter(Parameter.ENCODING))) {
200 throw new ValidationException(
201 "If the value type parameter is [BINARY], the inline"
202 + "encoding parameter MUST be specified with the value [BASE64]");
203 }
204 }
205 }
207 /**
208 * @return Returns the binary.
209 */
210 public final byte[] getBinary() {
211 return binary;
212 }
214 /**
215 * @return Returns the uri.
216 */
217 public final URI getUri() {
218 return uri;
219 }
221 /**
222 * Sets the current value of the Attach instance. If the specified
223 * value is encoded binary data, the value is decoded and stored in
224 * the binary field. Otherwise the value is assumed to be a URI
225 * location to binary data and is stored as such.
226 *
227 * @param aValue a string encoded binary or URI value
228 * @throws IOException where binary data cannot be decoded
229 * @throws URISyntaxException where the specified value is not a valid URI
230 */
231 public final void setValue(final String aValue) throws IOException,
232 URISyntaxException {
234 // determine if ATTACH is a URI or an embedded
235 // binary..
236 if (getParameter(Parameter.ENCODING) != null) {
237 // binary = Base64.decode(aValue);
238 try {
239 final BinaryDecoder decoder = DecoderFactory.getInstance()
240 .createBinaryDecoder(
241 (Encoding) getParameter(Parameter.ENCODING));
242 binary = decoder.decode(aValue.getBytes());
243 }
244 catch (UnsupportedEncodingException uee) {
245 Log log = LogFactory.getLog(Attach.class);
246 log.error("Error encoding binary data", uee);
247 }
248 catch (DecoderException de) {
249 Log log = LogFactory.getLog(Attach.class);
250 log.error("Error decoding binary data", de);
251 }
252 }
253 // assume URI..
254 else {
255 uri = Uris.create(aValue);
256 }
257 }
259 /**
260 * {@inheritDoc}
261 */
262 public final String getValue() {
263 if (getUri() != null) {
264 return Uris.decode(Strings.valueOf(getUri()));
265 }
266 else if (getBinary() != null) {
267 // return Base64.encodeBytes(getBinary(), Base64.DONT_BREAK_LINES);
268 try {
269 final BinaryEncoder encoder = EncoderFactory.getInstance()
270 .createBinaryEncoder(
271 (Encoding) getParameter(Parameter.ENCODING));
272 return new String(encoder.encode(getBinary()));
273 }
274 catch (UnsupportedEncodingException uee) {
275 Log log = LogFactory.getLog(Attach.class);
276 log.error("Error encoding binary data", uee);
277 }
278 catch (EncoderException ee) {
279 Log log = LogFactory.getLog(Attach.class);
280 log.error("Error encoding binary data", ee);
281 }
282 }
283 return null;
284 }
286 /**
287 * @param binary The binary to set.
288 */
289 public final void setBinary(final byte[] binary) {
290 this.binary = binary;
291 // unset uri..
292 this.uri = null;
293 }
295 /**
296 * @param uri The uri to set.
297 */
298 public final void setUri(final URI uri) {
299 this.uri = uri;
300 // unset binary..
301 this.binary = null;
302 }
303 }