001/* 002 * The MIT License 003 * Copyright (c) 2012 Microsoft Corporation 004 * 005 * Permission is hereby granted, free of charge, to any person obtaining a copy 006 * of this software and associated documentation files (the "Software"), to deal 007 * in the Software without restriction, including without limitation the rights 008 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 009 * copies of the Software, and to permit persons to whom the Software is 010 * furnished to do so, subject to the following conditions: 011 * 012 * The above copyright notice and this permission notice shall be included in 013 * all copies or substantial portions of the Software. 014 * 015 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 016 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 017 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 018 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 019 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 020 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 021 * THE SOFTWARE. 022 */ 023 024package microsoft.exchange.webservices.data.property.complex; 025 026import microsoft.exchange.webservices.data.core.EwsServiceXmlReader; 027import microsoft.exchange.webservices.data.core.EwsServiceXmlWriter; 028import microsoft.exchange.webservices.data.core.EwsUtilities; 029import microsoft.exchange.webservices.data.core.XmlAttributeNames; 030import microsoft.exchange.webservices.data.core.XmlElementNames; 031import microsoft.exchange.webservices.data.core.exception.service.local.ServiceValidationException; 032import microsoft.exchange.webservices.data.core.service.item.Item; 033import microsoft.exchange.webservices.data.core.enumeration.property.BodyType; 034import microsoft.exchange.webservices.data.core.enumeration.misc.ExchangeVersion; 035import microsoft.exchange.webservices.data.core.enumeration.misc.XmlNamespace; 036import microsoft.exchange.webservices.data.core.exception.service.local.ServiceVersionException; 037import microsoft.exchange.webservices.data.property.definition.PropertyDefinitionBase; 038import org.apache.commons.logging.Log; 039import org.apache.commons.logging.LogFactory; 040 041import java.util.Date; 042 043/** 044 * Represents an attachment to an item. 045 */ 046public abstract class Attachment extends ComplexProperty { 047 048 private static final Log LOG = LogFactory.getLog(Attachment.class); 049 050 /** 051 * The owner. 052 */ 053 private Item owner; 054 055 /** 056 * The id. 057 */ 058 private String id; 059 060 /** 061 * The name. 062 */ 063 private String name; 064 065 /** 066 * The content type. 067 */ 068 private String contentType; 069 070 /** 071 * The content id. 072 */ 073 private String contentId; 074 075 /** 076 * The content location. 077 */ 078 private String contentLocation; 079 080 /** 081 * The size. 082 */ 083 private int size; 084 085 /** 086 * The last modified time. 087 */ 088 private Date lastModifiedTime; 089 090 /** 091 * The is inline. 092 */ 093 private boolean isInline; 094 095 /** 096 * Initializes a new instance. 097 * 098 * @param owner The owner. 099 */ 100 protected Attachment(Item owner) { 101 this.owner = owner; 102 } 103 104 /** 105 * Throws exception if this is not a new service object. 106 */ 107 protected void throwIfThisIsNotNew() { 108 if (!this.isNew()) { 109 throw new UnsupportedOperationException("Attachments can't be updated."); 110 } 111 } 112 113 /** 114 * Sets value of field. 115 * <p/> 116 * We override the base implementation. Attachments cannot be modified so 117 * any attempts the change a property on an existing attachment is an error. 118 * 119 * @param <T> the generic type 120 * @param field The field 121 * @param value The value. 122 * @return true, if successful 123 */ 124 public <T> boolean canSetFieldValue(T field, T value) { 125 this.throwIfThisIsNotNew(); 126 return super.canSetFieldValue(field, value); 127 } 128 129 /** 130 * Gets the Id of the attachment. 131 * 132 * @return the id 133 */ 134 public String getId() { 135 return this.id; 136 } 137 138 /** 139 * Gets the name of the attachment. 140 * 141 * @return the name 142 */ 143 public String getName() { 144 return this.name; 145 } 146 147 /** 148 * Sets the name. 149 * 150 * @param value the new name 151 */ 152 public void setName(String value) { 153 if (this.canSetFieldValue(this.name, value)) { 154 this.name = value; 155 this.changed(); 156 } 157 } 158 159 /** 160 * Gets the content type of the attachment. 161 * 162 * @return the content type 163 */ 164 public String getContentType() { 165 return this.contentType; 166 } 167 168 /** 169 * Sets the content type. 170 * 171 * @param value the new content type 172 */ 173 public void setContentType(String value) { 174 if (this.canSetFieldValue(this.contentType, value)) { 175 this.contentType = value; 176 this.changed(); 177 } 178 } 179 180 /** 181 * Gets the content Id of the attachment. ContentId can be used as a 182 * custom way to identify an attachment in order to reference it from within 183 * the body of the item the attachment belongs to. 184 * 185 * @return the content id 186 */ 187 public String getContentId() { 188 return this.contentId; 189 } 190 191 /** 192 * Sets the content id. 193 * 194 * @param value the new content id 195 */ 196 public void setContentId(String value) { 197 if (this.canSetFieldValue(this.contentId, value)) { 198 this.contentId = value; 199 this.changed(); 200 } 201 } 202 203 /** 204 * Gets the content location of the attachment. ContentLocation can 205 * be used to associate an attachment with a Url defining its location on 206 * the Web. 207 * 208 * @return the content location 209 */ 210 public String getContentLocation() { 211 return this.contentLocation; 212 } 213 214 /** 215 * Sets the content location. 216 * 217 * @param value the new content location 218 */ 219 public void setContentLocation(String value) { 220 if (this.canSetFieldValue(this.contentLocation, value)) { 221 this.contentLocation = value; 222 this.changed(); 223 } 224 } 225 226 /** 227 * Gets the size of the attachment. 228 * 229 * @return the size 230 * @throws ServiceVersionException throws ServiceVersionException 231 */ 232 public int getSize() throws ServiceVersionException { 233 EwsUtilities.validatePropertyVersion(this.getOwner().getService(), ExchangeVersion.Exchange2010, "Size"); 234 return this.size; 235 } 236 237 /** 238 * Gets the date and time when this attachment was last modified. 239 * 240 * @return the last modified time 241 * @throws ServiceVersionException the service version exception 242 */ 243 public Date getLastModifiedTime() throws ServiceVersionException { 244 245 EwsUtilities.validatePropertyVersion(this.getOwner().getService(), 246 ExchangeVersion.Exchange2010, "LastModifiedTime"); 247 248 return this.lastModifiedTime; 249 250 } 251 252 /** 253 * Gets a value indicating whether this is an inline attachment. 254 * Inline attachments are not visible to end users. 255 * 256 * @return the checks if is inline 257 * @throws ServiceVersionException the service version exception 258 */ 259 public boolean getIsInline() throws ServiceVersionException { 260 EwsUtilities.validatePropertyVersion(this.getOwner().getService(), 261 ExchangeVersion.Exchange2010, "IsInline"); 262 return this.isInline; 263 264 } 265 266 /** 267 * Sets the checks if is inline. 268 * 269 * @param value the new checks if is inline 270 * @throws ServiceVersionException the service version exception 271 */ 272 public void setIsInline(boolean value) throws ServiceVersionException { 273 EwsUtilities.validatePropertyVersion(this.getOwner().getService(), 274 ExchangeVersion.Exchange2010, "IsInline"); 275 if (this.canSetFieldValue(this.isInline, value)) { 276 this.isInline = value; 277 this.changed(); 278 } 279 } 280 281 /** 282 * True if the attachment has not yet been saved, false otherwise. 283 * 284 * @return true, if is new 285 */ 286 public boolean isNew() { 287 return (this.getId() == null || this.getId().isEmpty()); 288 } 289 290 /** 291 * Gets the owner of the attachment. 292 * 293 * @return the owner 294 */ 295 public Item getOwner() { 296 return this.owner; 297 } 298 299 /** 300 * Gets the name of the XML element. 301 * 302 * @return XML element name. 303 */ 304 public abstract String getXmlElementName(); 305 306 /** 307 * Tries to read element from XML. 308 * 309 * @param reader The reader. 310 * @return True if element was read. 311 * @throws Exception the exception 312 */ 313 @Override 314 public boolean tryReadElementFromXml(EwsServiceXmlReader reader) 315 throws Exception { 316 317 try { 318 if (reader.getLocalName().equalsIgnoreCase( 319 XmlElementNames.AttachmentId)) { 320 try { 321 this.id = reader.readAttributeValue(XmlAttributeNames.Id); 322 } catch (Exception e) { 323 LOG.error(e); 324 return false; 325 } 326 if (this.getOwner() != null) { 327 String rootItemChangeKey = reader 328 .readAttributeValue(XmlAttributeNames. 329 RootItemChangeKey); 330 if (null != rootItemChangeKey && 331 !rootItemChangeKey.isEmpty()) { 332 this.getOwner().getRootItemId().setChangeKey( 333 rootItemChangeKey); 334 } 335 } 336 reader.readEndElementIfNecessary(XmlNamespace.Types, 337 XmlElementNames.AttachmentId); 338 return true; 339 } else if (reader.getLocalName().equalsIgnoreCase( 340 XmlElementNames.Name)) { 341 this.name = reader.readElementValue(); 342 return true; 343 } else if (reader.getLocalName().equalsIgnoreCase( 344 XmlElementNames.ContentType)) { 345 this.contentType = reader.readElementValue(); 346 return true; 347 } else if (reader.getLocalName().equalsIgnoreCase( 348 XmlElementNames.ContentId)) { 349 this.contentId = reader.readElementValue(); 350 return true; 351 } else if (reader.getLocalName().equalsIgnoreCase( 352 XmlElementNames.ContentLocation)) { 353 this.contentLocation = reader.readElementValue(); 354 return true; 355 } else if (reader.getLocalName().equalsIgnoreCase( 356 XmlElementNames.Size)) { 357 this.size = reader.readElementValue(Integer.class); 358 return true; 359 } else if (reader.getLocalName().equalsIgnoreCase( 360 XmlElementNames.LastModifiedTime)) { 361 this.lastModifiedTime = reader.readElementValueAsDateTime(); 362 return true; 363 } else if (reader.getLocalName().equalsIgnoreCase( 364 XmlElementNames.IsInline)) { 365 this.isInline = reader.readElementValue(Boolean.class); 366 return true; 367 } else { 368 return false; 369 } 370 } catch (Exception e) { 371 LOG.error(e); 372 return false; 373 } 374 } 375 376 /** 377 * Writes elements to XML. 378 * 379 * @param writer the writer 380 * @throws Exception the exception 381 */ 382 @Override 383 public void writeElementsToXml(EwsServiceXmlWriter writer) 384 throws Exception { 385 writer.writeElementValue(XmlNamespace.Types, XmlElementNames.Name, this 386 .getName()); 387 writer.writeElementValue(XmlNamespace.Types, 388 XmlElementNames.ContentType, this.getContentType()); 389 writer.writeElementValue(XmlNamespace.Types, XmlElementNames.ContentId, 390 this.getContentId()); 391 writer.writeElementValue(XmlNamespace.Types, 392 XmlElementNames.ContentLocation, this.getContentLocation()); 393 if (writer.getService().getRequestedServerVersion().ordinal() > 394 ExchangeVersion.Exchange2007_SP1 395 .ordinal()) { 396 writer.writeElementValue(XmlNamespace.Types, 397 XmlElementNames.IsInline, this.getIsInline()); 398 } 399 } 400 401 /** 402 * Load the attachment. 403 * 404 * @param bodyType Type of the body. 405 * @param additionalProperties The additional property. 406 * @throws Exception the exception 407 */ 408 protected void internalLoad(BodyType bodyType, 409 Iterable<PropertyDefinitionBase> additionalProperties) 410 throws Exception { 411 this.getOwner().getService().getAttachment(this, bodyType, 412 additionalProperties); 413 } 414 415 /** 416 * Validates this instance. 417 * 418 * @param attachmentIndex Index of this attachment. 419 * @throws ServiceValidationException the service validation exception 420 * @throws Exception the exception 421 */ 422 abstract void validate(int attachmentIndex) throws Exception; 423 424 /** 425 * Loads the attachment. Calling this method results in a call to EWS. 426 * 427 * @throws Exception the exception 428 */ 429 public void load() throws Exception { 430 this.internalLoad(null, null); 431 } 432 433}