001: /*
002: *
003: *
004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026:
027: package javax.wireless.messaging;
028:
029: import java.io.*;
030:
031: /**
032: * This class is defined by the JSR-205 specification
033: * <em>Wireless Messaging API (WMA)
034: * Version 2.0.</em>
035: */
036: // JAVADOC COMMENT ELIDED
037: public class MessagePart {
038:
039: // IMPL_NOTE: allow maximum part size to be externally set
040: /** Maximum size for message part. */
041: static int MAX_PART_SIZE_BYTES = 30720; // 30K
042:
043: // JAVADOC COMMENT ELIDED
044: void construct(byte[] contents, int offset, int length,
045: java.lang.String mimeType, java.lang.String contentId,
046: java.lang.String contentLocation, java.lang.String enc)
047: throws SizeExceededException {
048:
049: if (length > MAX_PART_SIZE_BYTES) {
050: throw new SizeExceededException("InputStream data exceeds "
051: + "MessagePart size limit");
052: }
053:
054: if (mimeType == null) {
055: throw new IllegalArgumentException(
056: "mimeType must be specified");
057: }
058: checkContentID(contentId);
059: checkContentLocation(contentLocation);
060: if (length < 0) {
061: throw new IllegalArgumentException("length must be >= 0");
062: }
063: if (contents != null && offset + length > contents.length) {
064: throw new IllegalArgumentException(
065: "offset + length exceeds contents length");
066: }
067: if (offset < 0) {
068: throw new IllegalArgumentException("offset must be >= 0");
069: }
070: checkEncodingScheme(enc);
071:
072: if (contents != null) {
073: this .content = new byte[length];
074: System.arraycopy(contents, offset, this .content, 0, length);
075: }
076:
077: this .mimeType = mimeType;
078: this .contentID = contentId;
079: this .contentLocation = contentLocation;
080: this .encoding = enc;
081: }
082:
083: // JAVADOC COMMENT ELIDED
084: public MessagePart(byte[] contents, int offset, int length,
085: java.lang.String mimeType, java.lang.String contentId,
086: java.lang.String contentLocation, java.lang.String enc)
087: throws SizeExceededException {
088: construct(contents, offset, length, mimeType, contentId,
089: contentLocation, enc);
090: }
091:
092: // JAVADOC COMMENT ELIDED
093: public MessagePart(byte[] contents, java.lang.String mimeType,
094: java.lang.String contentId,
095: java.lang.String contentLocation, java.lang.String enc)
096: throws SizeExceededException {
097: construct(contents, 0,
098: (contents == null ? 0 : contents.length), mimeType,
099: contentId, contentLocation, enc);
100: }
101:
102: /** Buffer size 2048. */
103: static final int BUFFER_SIZE = 2048;
104:
105: // JAVADOC COMMENT ELIDED
106: public MessagePart(java.io.InputStream is,
107: java.lang.String mimeType, java.lang.String contentId,
108: java.lang.String contentLocation, java.lang.String enc)
109: throws IOException, SizeExceededException {
110: byte[] bytes = {};
111: if (is != null) {
112: ByteArrayOutputStream accumulator = new ByteArrayOutputStream();
113: byte[] buffer = new byte[BUFFER_SIZE];
114: int readBytes = 0;
115: while ((readBytes = is.read(buffer)) != -1) {
116: accumulator.write(buffer, 0, readBytes);
117: }
118: bytes = accumulator.toByteArray();
119: }
120: construct(bytes, 0, bytes.length, mimeType, contentId,
121: contentLocation, enc);
122: }
123:
124: // JAVADOC COMMENT ELIDED
125: public byte[] getContent() {
126: if (content == null) {
127: return null;
128: }
129: byte[] copyOfContent = new byte[content.length];
130: System.arraycopy(content, 0, copyOfContent, 0, content.length);
131: return copyOfContent;
132: }
133:
134: // JAVADOC COMMENT ELIDED
135: public java.io.InputStream getContentAsStream() {
136: if (content == null) {
137: return new ByteArrayInputStream(new byte[0]);
138: } else {
139: return new ByteArrayInputStream(content);
140: }
141: }
142:
143: // JAVADOC COMMENT ELIDED
144: public java.lang.String getContentID() {
145: return contentID;
146: }
147:
148: // JAVADOC COMMENT ELIDED
149: public java.lang.String getContentLocation() {
150: return contentLocation;
151: }
152:
153: // JAVADOC COMMENT ELIDED
154: public java.lang.String getEncoding() {
155: return encoding;
156: }
157:
158: // JAVADOC COMMENT ELIDED
159: public int getLength() {
160: return content == null ? 0 : content.length;
161: }
162:
163: // JAVADOC COMMENT ELIDED
164: public java.lang.String getMIMEType() {
165: return mimeType;
166: }
167:
168: /** Content byte array. */
169: byte[] content;
170: /** MIME Content ID. */
171: String contentID;
172: /** Content location. */
173: String contentLocation;
174: /** Content encoding. */
175: String encoding;
176: /** MIME type. */
177: String mimeType;
178:
179: /**
180: * Verifies the content identifier.
181: * @param contentId content id to be checked
182: * @exception IllegalArgumentException if content id is not valid
183: */
184: static void checkContentID(String contentId)
185: throws IllegalArgumentException {
186: if (contentId == null) {
187: throw new IllegalArgumentException(
188: "contentId must be specified");
189: }
190: if (contentId.length() > 100) { // MMS Conformance limit
191: throw new IllegalArgumentException(
192: "contentId exceeds 100 char limit");
193: }
194: if (containsNonUSASCII(contentId)) {
195: throw new IllegalArgumentException(
196: "contentId must not contain non-US-ASCII characters");
197: }
198: }
199:
200: /**
201: * Verifies the content location.
202: * @param contentLoc content location to be checked.
203: * @exception IllegalArgumentException if content location is not valid.
204: */
205: static void checkContentLocation(String contentLoc)
206: throws IllegalArgumentException {
207: if (contentLoc != null) {
208: if (containsNonUSASCII(contentLoc)) {
209: throw new IllegalArgumentException(
210: "contentLocation must not contain non-US-ASCII characters");
211: }
212: if (contentLoc.length() > 100) { // MMS Conformance limit
213: throw new IllegalArgumentException(
214: "contentLocation exceeds 100 char limit");
215: }
216: }
217: }
218:
219: /**
220: * Verifies the content encoding.
221: * @param encoding The content encoding to be checked.
222: * @exception IllegalArgumentException if content encoding is not valid.
223: */
224: static void checkEncodingScheme(String encoding)
225: throws IllegalArgumentException {
226: // IMPL_NOTE: check for a valid encoding scheme
227: }
228:
229: /** Lowest valid ASCII character. */
230: static final char US_ASCII_LOWEST_VALID_CHAR = 32;
231:
232: /** Mask for ASCII character checks. */
233: static final char US_ASCII_VALID_BIT_MASK = 0x7F;
234:
235: /**
236: * Checks if a string contains non-ASCII characters.
237: * @param str Text to be checked.
238: * @return <code>true</code> if non-ASCII characters are found.
239: */
240: static boolean containsNonUSASCII(String str) {
241: int numChars = str.length();
242: for (int i = 0; i < numChars; ++i) {
243: char this Char = str.charAt(i);
244: if (this Char < US_ASCII_LOWEST_VALID_CHAR
245: || this Char != (this Char & US_ASCII_VALID_BIT_MASK))
246: return true;
247: }
248: return false;
249: }
250: }
|