001package ball.activation; 002/*- 003 * ########################################################################## 004 * Utilities 005 * %% 006 * Copyright (C) 2008 - 2022 Allen D. Ball 007 * %% 008 * Licensed under the Apache License, Version 2.0 (the "License"); 009 * you may not use this file except in compliance with the License. 010 * You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, software 015 * distributed under the License is distributed on an "AS IS" BASIS, 016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 017 * See the License for the specific language governing permissions and 018 * limitations under the License. 019 * ########################################################################## 020 */ 021import java.io.IOException; 022import java.io.InputStream; 023import java.io.OutputStream; 024import java.lang.reflect.InvocationTargetException; 025import javax.activation.DataSource; 026 027/** 028 * {@link DataSource} default method implementations. 029 * 030 * @author {@link.uri mailto:ball@hcf.dev Allen D. Ball} 031 */ 032public interface DataSourceDefaultMethods extends DataSource { 033 034 /** 035 * {@link.rfc 2045} {@value #CONTENT_TYPE} 036 */ 037 public static final String CONTENT_TYPE = "Content-Type"; 038 039 /** 040 * {@link.rfc 2045} {@value #APPLICATION_OCTET_STREAM} 041 */ 042 public static final String APPLICATION_OCTET_STREAM = "application/octet-stream"; 043 044 /** 045 * {@link.rfc 3023} {@value #APPLICATION_XML} 046 */ 047 public static final String APPLICATION_XML = "application/xml"; 048 049 /** 050 * {@link.rfc 2045} {@value #TEXT_PLAIN} 051 */ 052 public static final String TEXT_PLAIN = "text/plain"; 053 054 /** 055 * {@link.rfc 2045} {@value #TEXT_HTML} 056 */ 057 public static final String TEXT_HTML = "text/html"; 058 059 default void setName(String name) { 060 throw new UnsupportedOperationException(); 061 } 062 063 default void setContentType(String type) { 064 throw new UnsupportedOperationException(); 065 } 066 067 /** 068 * @throws UnsupportedOperationException 069 * Unless overridden by subclass 070 * implementation. 071 */ 072 @Override 073 default InputStream getInputStream() throws IOException { 074 throw new UnsupportedOperationException(); 075 } 076 077 /** 078 * @throws UnsupportedOperationException 079 * Unless overridden by subclass 080 * implementation. 081 */ 082 @Override 083 default OutputStream getOutputStream() throws IOException { 084 throw new UnsupportedOperationException(); 085 } 086 087 /** 088 * Method to clear the {@link DataSource} and discard any input on any 089 * open {@link #getOutputStream()}. 090 * 091 * @throws UnsupportedOperationException 092 * If {@link #getOutputStream()} throws 093 * {@link UnsupportedOperationException}. 094 */ 095 default void clear() { 096 try { 097 getOutputStream().close(); 098 } catch (IOException exception) { 099 throw new IllegalStateException(exception); 100 } 101 } 102 103 /** 104 * Method to get the number of bytes stored in {@link.this} 105 * {@link DataSource}. Default implementation returns {@code -1}. 106 * 107 * @return The number of bytes stored in {@link.this} 108 * {@link DataSource}; {@code -1} if the count is unknown. 109 */ 110 default long length() { return -1; } 111 112 /** 113 * Method to "wrap" the {@link InputStream} returned by 114 * {@link #getInputStream()}into {@link InputStream} instances. 115 * 116 * @param types The {@link InputStream} implementation 117 * {@link Class}es. 118 * 119 * @return The "wrapped" {@link InputStream}. 120 * 121 * @throws IOException If an I/O error occurs. 122 */ 123 default InputStream getInputStream(Class<?>... types) throws IOException { 124 return wrap(getInputStream(), types); 125 } 126 127 /** 128 * Method to "wrap" the {@link OutputStream} returned by 129 * {@link #getOutputStream()}into {@link OutputStream} instances. 130 * 131 * @param types The {@link OutputStream} implementation 132 * {@link Class}es. 133 * 134 * @return The "wrapped" {@link OutputStream}. 135 * 136 * @throws IOException If an I/O error occurs. 137 */ 138 default OutputStream getOutputStream(Class<?>... types) throws IOException { 139 return wrap(getOutputStream(), types); 140 } 141 142 /** 143 * Method to "wrap" an {@link InputStream} into {@link InputStream} 144 * instances. 145 * 146 * @param in The {@link InputStream}. 147 * @param types The {@link InputStream} implementation 148 * {@link Class}es. 149 * 150 * @return The "wrapped" {@link InputStream}. 151 * 152 * @throws IOException If any of the wrapping streams throw an 153 * {@link IOException}. 154 */ 155 default InputStream wrap(InputStream in, Class<?>... types) throws IOException { 156 try { 157 for (Class<?> type : types) { 158 in = 159 type.asSubclass(InputStream.class) 160 .getConstructor(InputStream.class) 161 .newInstance(in); 162 } 163 } catch (InvocationTargetException exception) { 164 Throwable cause = exception.getCause(); 165 166 if (cause instanceof IOException) { 167 throw (IOException) cause; 168 } else if (cause instanceof RuntimeException) { 169 throw (RuntimeException) cause; 170 } else if (cause instanceof Error) { 171 throw (Error) cause; 172 } else { 173 throw new IllegalArgumentException(exception); 174 } 175 } catch (RuntimeException exception) { 176 throw exception; 177 } catch (Exception exception) { 178 throw new IllegalArgumentException(exception); 179 } 180 181 return in; 182 } 183 184 /** 185 * Method to "wrap" an {@link OutputStream} into {@link OutputStream} 186 * instances. 187 * 188 * @param out The {@link OutputStream}. 189 * @param types The {@link OutputStream} implementation 190 * {@link Class}es. 191 * 192 * @return The "wrapped" {@link OutputStream}. 193 * 194 * @throws IOException If any of the wrapping streams throw an 195 * {@link IOException}. 196 */ 197 default OutputStream wrap(OutputStream out, Class<?>... types) throws IOException { 198 try { 199 for (Class<?> type : types) { 200 out = 201 type.asSubclass(OutputStream.class) 202 .getConstructor(OutputStream.class) 203 .newInstance(out); 204 } 205 } catch (InvocationTargetException exception) { 206 Throwable cause = exception.getCause(); 207 208 if (cause instanceof IOException) { 209 throw (IOException) cause; 210 } else if (cause instanceof RuntimeException) { 211 throw (RuntimeException) cause; 212 } else if (cause instanceof Error) { 213 throw (Error) cause; 214 } else { 215 throw new IllegalArgumentException(exception); 216 } 217 } catch (RuntimeException exception) { 218 throw exception; 219 } catch (Exception exception) { 220 throw new IllegalArgumentException(exception); 221 } 222 223 return out; 224 } 225}